#include <GL/glew.h>
#include <GL/glut.h>

#include "environment.h"
#include <vector>
#include <string>
#include <iostream>
#include <string.h>
#include "Vector3.h"
#include "Triangle.h"
#include "Vector2.h"
#include "Utility.h"
#include "geometry.h"
#include "command.h"
#include "robot.h"
#include "obstacle.h"
#include "cuda_vertex.h"
#include "defs.h"

EnvironmentBase::EnvironmentBase(std::string const& cmd_file_name)
{
	int i;
	
	m_cmd = new PlanningCommand;
	std::cout << cmd_file_name << std::endl;
	m_cmd->parse(cmd_file_name);
	m_cmd->print();
	
	for(i = 0; i < m_cmd->m_num_obstacles; ++i)
	{
		ObstacleBase* obs = new ObstacleBase(this);
		obs->load(m_cmd->m_obstacle_file_names[i], m_cmd->m_obs_scales[i]);
		obs->transf = VecToSE3(m_cmd->m_obs_confs + 6 * i);
		m_obstacles_.push_back(obs);
	}
	
	switch(m_cmd->m_problem_type)
	{
	case PT_ARTICULATED:
		m_robot = new ArticulatedRobot(this);
		m_robot->load(m_cmd->m_robot_file_name);
		break;
	case PT_RIGID_3T:
		m_robot = new RigidBodyRobot3T(this);
		m_robot->load(m_cmd->m_robot_file_name);
		break;
	case PT_RIGID_3T3R:
		m_robot = new RigidBodyRobot3T3R(this);
		m_robot->load(m_cmd->m_robot_file_name);
		break;
	default:
		std::cout << "Error: robot file type not supported!" << std::endl;
	}
	
	// transform list to array (in debug mode, CUDA seems can not handle std::list in .cu file)
	m_num_obstacles = m_obstacles_.size();
	m_obstacles = new ObstacleBase* [m_num_obstacles];
	i = 0;
	for(std::list<ObstacleBase*>::iterator it = m_obstacles_.begin(); it != m_obstacles_.end(); ++it)
	{
		m_obstacles[i] = *it;
		i++;
	}
	
	m_num_models = m_models_.size();
	m_models = new ModelInstance* [m_num_models];
	i = 0;
	for(std::list<ModelInstance*>::iterator it = m_models_.begin(); it != m_models_.end(); ++it)
	{
		m_models[i] = *it;
		i++;
	}
	
	assert(m_cmd->m_dof == m_robot->dim_state);
	
	//for(int i = 0; i < m_cmd->m_dof; ++i)
	//{
	//	if(m_cmd->m_dof_topologies[i] == DTT_CIRCLE)
	//		std::cout << "C " << std::endl;
	//	else
	//		std::cout << "E " << std::endl;
	//	std::cout << m_cmd->m_dof_lower_bounds[i] << " " << m_cmd->m_dof_upper_bounds[i] << std::endl;
	//}

	if(m_cmd->m_problem_type == PT_ARTICULATED)
	{
		ArticulatedRobot* robot = (ArticulatedRobot*)m_robot;
		for(int i = 0; i < robot->joint_num; ++i)
		{
			robot->joints[i].locked = false;
			for(int j = 0; j < m_cmd->m_num_lockedjoints; ++j)
			{
				if(robot->joints[i].param_idx == m_cmd->m_lockedjoint_paramids[j])
				{
					robot->joints[i].locked = true;
					break;
				}
			}
		}

		for(int i = 0; i < m_cmd->m_num_lockedjoints; ++i)
		{
			int locked_paramid = m_cmd->m_lockedjoint_paramids[i];
			assert(m_cmd->m_init_confs[locked_paramid] ==m_cmd->m_goal_confs[locked_paramid]);
			m_robot->state_lower_bounds[locked_paramid] = m_cmd->m_init_confs[locked_paramid];
			m_robot->state_upper_bounds[locked_paramid] = m_cmd->m_init_confs[locked_paramid];
		}
	}
	
	
	//if(m_cmd->m_problem_type == PT_ARTICULATED)
	//{
	//	((ArticulatedRobot*)m_robot)->save_rob("transformed.rob");
	//}

	post_process();
}

EnvironmentBase::~EnvironmentBase()
{
	delete m_cmd;
	m_cmd = NULL;
}

void EnvironmentBase::set_robot(RobotBase* robot)
{
	m_robot = robot;
}
RobotBase* EnvironmentBase::get_robot() const
{
	return m_robot;
}

void EnvironmentBase::add_obstacle(ObstacleBase* obstacle)
{
	m_obstacles_.push_back(obstacle);
}

ObstacleBase* EnvironmentBase::get_obstacle(int i) const
{
	assert(m_obstacles);
	if(i < m_num_obstacles)
		return m_obstacles[i];
	return NULL;
}

int EnvironmentBase::obstacle_size() const
{
	return m_num_obstacles;
}

void EnvironmentBase::add_model(ModelInstance* model)
{
	m_models_.push_back(model);
}


void EnvironmentBase::print() const
{
}

void EnvironmentBase::merge_obstacles()
{

}

void EnvironmentBase::post_process()
{

	if(m_robot->robot_type == RT_ARTICULATED)
	{
		ArticulatedRobot* robot = (ArticulatedRobot*)m_robot;

		m_uncompressed_info.used = true;
		m_uncompressed_info.full_dim_state = robot->dim_state;
		m_uncompressed_info.full_joint_num = robot->joint_num;
		m_uncompressed_info.full_joint_param_id = new short [robot->joint_num];
		m_uncompressed_info.full_init_confs = new float[robot->dim_state];
		m_uncompressed_info.full_goal_confs = new float[robot->dim_state];
		m_uncompressed_info.full_joint_compressed_param_id = new short[robot->joint_num];
		for(int i = 0; i < robot->joint_num; ++i)
		{
			m_uncompressed_info.full_joint_param_id[i] = robot->joints[i].param_idx;
			m_uncompressed_info.full_joint_compressed_param_id[i] = ROBOT_NOPARAM_NODE;
		}
		for(int i = 0; i < robot->dim_state; ++i)
		{
			m_uncompressed_info.full_init_confs[i] = m_cmd->m_init_confs[i];
			m_uncompressed_info.full_goal_confs[i] = m_cmd->m_goal_confs[i];
		}

		int new_dim = m_cmd->m_dof - m_cmd->m_num_lockedjoints;
		int* group_ids = new int[robot->joint_num];
		std::vector<int> group_reps;
		for(int i = 0; i < robot->joint_num; ++i)
		{
			if(robot->joints[i].joint_type == JT_FIXED || robot->joints[i].locked)
			{
				int parent_id = robot->joints[i].parent_idx;
				if(parent_id == ROBOT_NOPARENT_NODE)
				{
					group_ids[i] = i;
					group_reps.push_back(i);
				}

				while(parent_id != -1)
				{
					if(parent_id < i && (robot->joints[parent_id].joint_type == JT_FIXED || robot->joints[parent_id].locked))
					{
						group_ids[i] = group_ids[parent_id];
						break;
					}
					else if(robot->joints[parent_id].joint_type == JT_FIXED || robot->joints[parent_id].locked)
					{
						parent_id = robot->joints[parent_id].parent_idx;
						continue;
					}	
					else
					{
						group_ids[i] = parent_id;
						break;
					}
				}
			}
			else 
			{
				group_ids[i] = i;
				group_reps.push_back(i);
			}
		}

		//for(int i = 0; i < group_reps.size(); ++i)
		//	printf("%d ", group_reps[i]);
		//printf("\n");
		//for(int i = 0; i < robot->joint_num; ++i)
		//	printf("%d ", group_ids[i]);
		//printf("\n");


		ModelInstance** models = new ModelInstance*[group_reps.size()];
		for(int i = 0; i < group_reps.size(); ++i)
		{
			models[i] = new ModelInstance;
			int repres_id = group_reps[i];
			char name[50];
			sprintf(name, "%dgroup.obj", i);
			models[i]->modelFileName = std::string(name);
			//std::cout << models[i]->modelFileName << std::endl;

			std::vector<int> group;
			int nVerts = 0, nTris = 0;
			for(int j = 0; j < robot->joint_num; ++j)
			{
				if(group_ids[j] == repres_id)
				{
					group.push_back(j);
					if(robot->joints[j].model)
					{
						nVerts += robot->joints[j].model->nVerts;
						nTris += robot->joints[j].model->nTris;
					}
				}
			}

			if(nVerts == 0)
			{
				delete models[i];
				models[i] = NULL;
				continue;
			}

			SSEVertex* verlist = (SSEVertex *)malloc(sizeof(SSEVertex) * nVerts);
			Triangle* trilist = new Triangle[nTris];

			SSEVertex* curVecListPointer = verlist;
			Triangle* curTriListPointer = trilist;
			int triStartId = 0;

			for(int j = 0; j < group.size(); ++j)
			{
				int joint_id = group[j];
				if(robot->joints[joint_id].model)
				{
					ArticulatedRobot::Joint joint = robot->joints[joint_id];
					if(joint_id == repres_id)
					{
						if(joint.joint_type == JT_FIXED)
						{
							for(int k = 0; k < joint.model->nVerts; ++k)
							{
								curVecListPointer[k] = joint.model->verlist[k];
							}
						}
						else if(joint.locked)
						{	
							Transform t;
							if(joint.joint_type == JT_REVOLUTE || joint.joint_type == JT_CONTINUOUS)
								t = make_rotate_transform(joint.axis[0], joint.axis[1], joint.axis[2], m_cmd->m_init_confs[joint.param_idx]);
							else if(joint.joint_type == JT_PRISMATIC)
								t = make_transl_transform(joint.axis[0] * m_cmd->m_init_confs[joint.param_idx],
								joint.axis[1] * m_cmd->m_init_confs[joint.param_idx],
								joint.axis[2] * m_cmd->m_init_confs[joint.param_idx]);
							else
								t.set_identity();

							for(int k = 0; k < joint.model->nVerts; ++k)
							{
								SSEVertex tmpV;
								t.apply(tmpV.e, (joint.model->verlist[k]).e);
								curVecListPointer[k] = tmpV;
							}
						}
						else
						{
							for(int k = 0; k < joint.model->nVerts; ++k)
							{
								curVecListPointer[k] = joint.model->verlist[k];
							}
						}
						curVecListPointer += joint.model->nVerts;
					}
					else
					{
						Transform t;
						Transform tmp = joint.T0;
						short param_id = joint.param_idx;
						

						if(joint.joint_type != JT_FIXED && joint.locked)
						{
							if(joint.joint_type == JT_REVOLUTE || joint.joint_type == JT_CONTINUOUS)
							{
								tmp.append(make_rotate_transform(joint.axis[0], joint.axis[1], joint.axis[2], m_cmd->m_init_confs[param_id]));
							}
							else if(joint.joint_type == JT_PRISMATIC)
							{
								tmp.append(make_transl_transform(joint.axis[0] * m_cmd->m_init_confs[param_id],
																joint.axis[1] * m_cmd->m_init_confs[param_id],
																joint.axis[2] * m_cmd->m_init_confs[param_id]));
							}
						}

						t = tmp;
						short parent_id = joint.parent_idx;
						while(parent_id != repres_id && parent_id != ROBOT_NOPARAM_NODE)
						{
							ArticulatedRobot::Joint parent_joint = robot->joints[parent_id];
							tmp = parent_joint.T0;
							param_id = parent_joint.param_idx;
							
							if(parent_joint.joint_type != JT_FIXED && parent_joint.locked)
							{
								if(parent_joint.joint_type == JT_REVOLUTE || parent_joint.joint_type == JT_CONTINUOUS)
								{
									tmp.append(make_rotate_transform(parent_joint.axis[0], parent_joint.axis[1], parent_joint.axis[2], m_cmd->m_init_confs[param_id]));
								}
								else if(parent_joint.joint_type == JT_PRISMATIC)
								{
									tmp.append(make_transl_transform(parent_joint.axis[0] * m_cmd->m_init_confs[param_id],
										parent_joint.axis[1] * m_cmd->m_init_confs[param_id],
										parent_joint.axis[2] * m_cmd->m_init_confs[param_id]));
								}
							}
							
							t.append_left(tmp);
							parent_id = parent_joint.parent_idx;
						}

						for(int k = 0; k < joint.model->nVerts; ++k)
						{
							SSEVertex tmpV;
							t.apply(tmpV.e, (joint.model->verlist[k]).e);
							curVecListPointer[k] = tmpV;
						}
						curVecListPointer += joint.model->nVerts;
					}

					for(int k = 0; k < joint.model->nTris; ++k)
					{
						Triangle tmpT = joint.model->trilist[k];
						tmpT.p[0] += triStartId;
						tmpT.p[1] += triStartId;
						tmpT.p[2] += triStartId;
						curTriListPointer[k] =tmpT;
					}
					curTriListPointer += joint.model->nTris;
					triStartId += joint.model->nVerts;
				}
			}

			models[i]->nVerts = nVerts;
			models[i]->nTris = nTris;
			models[i]->verlist = verlist;
			models[i]->trilist = trilist;
		}

		

		ArticulatedRobot::Joint* joints = new ArticulatedRobot::Joint[group_reps.size()];
		int active_param_id = 0;
		for(int i = 0; i < group_reps.size(); ++i)
		{
			//printf("%d\n", robot->joints[group_reps[i]].parent_idx);
			int repre_id = group_reps[i];
			joints[i].model = models[i];
			for(int j = 0; j < 3; ++j)
				joints[i].axis[j] = robot->joints[repre_id].axis[j];
			joints[i].T0 = robot->joints[repre_id].T0;

			/* May need to represent joints[i].T0 by t, above seems have problem!!!
			Transform t = robot->joints[repre_id].T0;
			short parent_id = robot->joints[repre_id].parent_idx;
				
			while (parent_id != ROBOT_NOPARENT_NODE)
			{
				ArticulatedRobot::Joint joint = robot->joints[parent_id];
				Transform tmp = joint.T0;
				short param_id = joint.param_idx;
				
				if (joint.joint_type == JT_REVOLUTE || joint.joint_type == JT_CONTINUOUS)
				{
					tmp.append(make_rotate_transform(joint.axis[0], joint.axis[1], joint.axis[2], m_cmd->m_init_confs[param_id]));
				}
				else if (joint.joint_type == JT_PRISMATIC)
				{
					tmp.append(make_transl_transform(joint.axis[0] * m_cmd->m_init_confs[param_id],
					                                 joint.axis[1] * m_cmd->m_init_confs[param_id],
					                                 joint.axis[2] * m_cmd->m_init_confs[param_id]));
				}
				
				t.append_left(tmp);
				parent_id = joint.parent_idx;
			}
			*/

			joints[i].joint_type = robot->joints[repre_id].joint_type;
			joints[i].name = robot->joints[repre_id].name;
			joints[i].j_min = robot->joints[repre_id].j_min;
			joints[i].j_max = robot->joints[repre_id].j_max;
			joints[i].locked = robot->joints[repre_id].locked;


			if(robot->joints[repre_id].param_idx == -1)
				joints[i].param_idx = -1;
			else
			{
				joints[i].param_idx = active_param_id;
				active_param_id++;
			}

			m_uncompressed_info.full_joint_compressed_param_id[repre_id] = joints[i].param_idx; // old joint num, new param id

			if(robot->joints[repre_id].parent_idx == -1)
				joints[i].parent_idx = -1;
			else
			{
				int parent_group_id = group_ids[robot->joints[repre_id].parent_idx]; //
				int parent_id = -1;
				for(int j = 0; j < group_reps.size(); ++j)
				{
					if(group_reps[j] == parent_group_id)
						parent_id = j;
				}


				joints[i].parent_idx = parent_id;
			}
		}

		//for(int i = 0; i < group_reps.size(); ++i)
		//{
		//	printf("parent_id %d\n", joints[i].parent_idx);
		//}
		//for(int i = 0; i < group_reps.size(); ++i)
		//{
		//	printf("param_id %d\n", joints[i].param_idx);
		//}

		ArticulatedRobot* compressed_robot = new ArticulatedRobot(this);
		compressed_robot->joints = joints;
		for(int i = 0; i < robot->noSelfcollision_info.size(); ++i)
		{
			ArticulatedRobot::NoSelfCollisionPair pair = robot->noSelfcollision_info[i];
			int joint1 = pair.joint1;
			int joint2 = pair.joint2;
			if(group_ids[joint1] != group_ids[joint2])
			{
				int new_joint1 = -1;
				int new_joint2 = -1;
				for(int j = 0; j < group_reps.size(); ++j)
				{
					if(group_reps[j] == group_ids[joint1])
					{
						new_joint1 = j;
					}
					if(group_reps[j] == group_ids[joint2])
					{
						new_joint2 = j;
					}
				}
				compressed_robot->noSelfcollision_info.push_back(ArticulatedRobot::NoSelfCollisionPair(new_joint1, new_joint2));
				//printf("new pair: %d %d\n", new_joint1, new_joint2);
			}
		}

		compressed_robot->dim_state = active_param_id;
		//printf("%d\n", active_param_id);
		compressed_robot->joint_num = group_reps.size();
		compressed_robot->state_lower_bounds = new float[compressed_robot->dim_state];
		compressed_robot->state_upper_bounds = new float[compressed_robot->dim_state];
		compressed_robot->dist_state_coeffs = new float[compressed_robot->dim_state];

		for(int i = 0; i < group_reps.size(); ++i)
		{
			int param_id = joints[i].param_idx;
			if(param_id != -1)
			{
				int old_joint_id = group_reps[i];
				int old_param_id = robot->joints[old_joint_id].param_idx;

				//printf("%d %d\n", param_id, old_param_id);

				if(old_param_id == -1) printf("Error: old_param_id should never be -1\n");
				compressed_robot->state_lower_bounds[param_id] = robot->state_lower_bounds[old_param_id];
				compressed_robot->state_upper_bounds[param_id] = robot->state_upper_bounds[old_param_id];
				compressed_robot->dist_state_coeffs[param_id] = robot->dist_state_coeffs[old_param_id];
			}
		}

		//for(int i = 0; i < compressed_robot->dim_state; ++i)
		//{
		//	printf("%f %f %f\n", compressed_robot->state_lower_bounds[i], compressed_robot->state_upper_bounds[i], compressed_robot->dist_state_coeffs[i]);
		//}


		//compressed command
		PlanningCommand* compressed_cmd = new PlanningCommand;

		compressed_cmd->m_collision_method = m_cmd->m_collision_method;
		compressed_cmd->m_sample_generate_method = m_cmd->m_sample_generate_method;
		compressed_cmd->m_knn_k = m_cmd->m_knn_k;
		compressed_cmd->m_query_k = m_cmd->m_query_k;
		compressed_cmd->m_LSH_L = m_cmd->m_LSH_L;
		compressed_cmd->m_LSH_W_PARAM = m_cmd->m_LSH_W_PARAM;
		compressed_cmd->m_ccd_type = m_cmd->m_ccd_type;
		compressed_cmd->m_check_resolution = m_cmd->m_check_resolution;
		compressed_cmd->m_problem_type = m_cmd->m_problem_type;
		compressed_cmd->m_proximity_method = m_cmd->m_proximity_method;
		compressed_cmd->m_graphsearch_method = m_cmd->m_graphsearch_method;
		compressed_cmd->m_prm_nSamples = m_cmd->m_prm_nSamples;
		compressed_cmd->m_n_queries = m_cmd->m_n_queries;
		compressed_cmd->m_enable_preclustering = m_cmd->m_enable_preclustering;
		compressed_cmd->m_preclustering_cluster_num = m_cmd->m_preclustering_cluster_num;



		compressed_cmd->m_n_queries_init = m_cmd->m_n_queries_init;
		compressed_cmd->m_n_queries_goal = m_cmd->m_n_queries_goal;

		compressed_cmd->m_obs_confs = new float[m_num_obstacles * 6];
		for(int i = 0; i < m_num_obstacles * 6; ++i)
			compressed_cmd->m_obs_confs[i] = m_cmd->m_obs_confs[i];

		compressed_cmd->m_init_confs = new float[compressed_robot->dim_state * compressed_cmd->m_n_queries];
		compressed_cmd->m_goal_confs = new float[compressed_robot->dim_state * compressed_cmd->m_n_queries];
		compressed_cmd->m_dof_lower_bounds = new float[compressed_robot->dim_state];
		compressed_cmd->m_dof_upper_bounds = new float[compressed_robot->dim_state];
		compressed_cmd->m_dof_weights = new float[compressed_robot->dim_state];
		compressed_cmd->m_dof_topologies = new DOFTopoType[compressed_robot->dim_state];
		
		for(int i = 0; i < group_reps.size(); ++i)
		{
			int param_id = joints[i].param_idx;
			if(param_id != -1)
			{
				int old_joint_id = group_reps[i];
				int old_param_id = robot->joints[old_joint_id].param_idx;

				if(old_param_id == -1) printf("Error: old param_id should never be -1\n");
				for(int j = 0; j < compressed_cmd->m_n_queries; ++j)
				{
					compressed_cmd->m_init_confs[param_id + j * compressed_robot->dim_state] = m_cmd->m_init_confs[old_param_id + j * robot->dim_state];
					compressed_cmd->m_goal_confs[param_id + j * compressed_robot->dim_state] = m_cmd->m_goal_confs[old_param_id + j * robot->dim_state];
				}
				compressed_cmd->m_dof_lower_bounds[param_id] = m_cmd->m_dof_lower_bounds[old_param_id];
				compressed_cmd->m_dof_upper_bounds[param_id] = m_cmd->m_dof_upper_bounds[old_param_id];
				compressed_cmd->m_dof_topologies[param_id] = m_cmd->m_dof_topologies[old_param_id];
			}
		}

		delete m_cmd; m_cmd = compressed_cmd;

		m_models_.clear();
		for(int i = 0; i < group_reps.size(); ++i)
		{
			if(models[i])
				m_models_.push_back(models[i]);
		}
		for(int i = 0; i < m_num_obstacles; ++i)
			m_models_.push_back(m_obstacles[i]->model);


		for(int i = 0; i < m_num_models; ++i)
		{
			if(m_models[i]->modelType == ROBOT_MODEL)
			delete m_models[i];
		}
		delete m_models;


		delete [] models;
		m_models = new ModelInstance* [m_models_.size()];
		m_num_models = m_models_.size();
		
		int m_id = 0;
		for(std::list<ModelInstance*>::iterator it = m_models_.begin(); it != m_models_.end(); ++it)
		{
			m_models[m_id] = *it;
			m_id++;
		}

		delete m_robot;
		m_robot = compressed_robot;



		delete [] group_ids;		
	}
}

void EnvironmentBase::setup_GL_instance()
{
	int maxV, maxI;
	glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxV);
	glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxI);
	
	std::cout << "OpenGL VBO max vertices " << maxV << " " << "max indices " << maxI << std::endl;
	
	//for(std::list<ModelInstance*>::iterator it = m_models_.begin(); it != m_models_.end(); ++it)
	for(int i = 0; i < m_num_models; ++i)
	{
		ModelInstance* object = m_models[i];
		
		VBOVertex* modelVertices = new VBOVertex[object->nVerts];
		unsigned int* modelIndices = new unsigned int[object->nTris * 3];
		
		for(unsigned int t = 0; t < object->nVerts; ++t)
		{
			modelVertices[t].v = object->verlist[t];
		}
		
		for(unsigned int t = 0; t < object->nTris; ++t)
		{
			const Triangle& tri = object->trilist[t];
			modelIndices[3 * t] = tri.p[0];
			modelIndices[3 * t + 1] = tri.p[1];
			modelIndices[3 * t + 2] = tri.p[2];
		}
		
		glGenBuffers(1, &object->vbo_Vertex);
		glBindBuffer(GL_ARRAY_BUFFER, object->vbo_Vertex);
		glBufferData(GL_ARRAY_BUFFER, object->nVerts * sizeof(VBOVertex), modelVertices, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		
		//VBOVertex* modelVertices = new VBOVertex[object->nTris * 3];
		//unsigned int* modelIndices = new unsigned int[object->nTris * 3];
		//
		//for(unsigned int t = 0; t < object->nTris; ++t)
		//{
		//	const Triangle& tri = object->trilist[t];
		//	int tmpid[3];
		//	tmpid[0] = t * 3;
		//	tmpid[1] = t * 3 + 1;
		//	tmpid[2] = t * 3 + 2;
		//
		//	modelVertices[tmpid[0]].v = object->verlist[tri.p[0]];
		//	modelVertices[tmpid[1]].v = object->verlist[tri.p[1]];
		//	modelVertices[tmpid[2]].v = object->verlist[tri.p[2]];
		//
		//	modelIndices[tmpid[0]] = tmpid[0];
		//	modelIndices[tmpid[1]] = tmpid[1];
		//	modelIndices[tmpid[2]] = tmpid[2];
		//}
		
		//printf("ntris: %d\n", object->nTris);
		//
		//glGenBuffers(1, &object->vbo_Vertex);
		//glBindBuffer(GL_ARRAY_BUFFER, object->vbo_Vertex);
		//glBufferData(GL_ARRAY_BUFFER, object->nTris * 3 * sizeof(VBOVertex), modelVertices, GL_STATIC_DRAW);
		//glBindBuffer(GL_ARRAY_BUFFER, 0);
		
		switch(glGetError())
		{
		case GL_OUT_OF_MEMORY:
			printf("out of memory\n");
		default:
			;
		}
		
		glGenBuffers(1, &object->vbo_TriIndex);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->vbo_TriIndex);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, object->nTris * 3 * sizeof(unsigned int), modelIndices, GL_STATIC_DRAW);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		
		delete [] modelIndices;
		modelIndices = NULL;
		delete [] modelVertices;
		modelVertices = NULL;
	}
}
